package com.diy.sigmund.diycommon.spring.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 控制层日志切面
 *
 * @author ylm-sigmund
 * @since 2021/6/2 22:08
 */
@Component
@Aspect
public class ControllerLogAspect1 {

    private static final Logger log = LoggerFactory.getLogger(ControllerLogAspect1.class);

    /** 虽然这里无法查看到被使用的方法，但是该切面可以应用到 */
    @Pointcut("execution(public * com.diy.sigmund..controller..*(..))")
    // @Pointcut("execution(public * com.diy.sigmund..controller..*(..))")
    public void pointcut() {
    }

    /**
     * <br>ProceedingJoinPoint is only supported for around advice
     * <br>后置增强相当于finally
     * <br>正常执行顺序:环绕增强(前置)Around->前置增强Before->环绕增强(后置)Around->后置增强After->返回增强AfterReturning
     * <br>异常执行顺序:环绕增强(前置)Around->前置增强Before->后置增强After->异常增强AfterThrowing
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        // log.info(LogConstant.SPRING_LOG, "控制层日志切面 around 开始" + getMethodName(pjp));
        Object proceed = pjp.proceed();
        // log.info(LogConstant.SPRING_LOG, "控制层日志切面 around 结束" + getMethodName(pjp));
        return proceed;
    }

    @NotNull
    private String getMethodName(ProceedingJoinPoint pjp) {
        return pjp.getSignature().getDeclaringType() + "." + pjp.getSignature().getName();
    }

    @Before("pointcut()")
    public void before() {
        // log.info(LogConstant.SPRING_LOG, "控制层日志切面 before");
    }

    /** 在方法执行之后调用的通知，无论方法执行是否成功 */
    @After("pointcut()")
    public void after() {
        // log.info(LogConstant.SPRING_LOG, "控制层日志切面 after");
    }

    /** 仅当方法成功完成后执行的通知 */
    @AfterReturning("pointcut()")
    public void afterReturning() {
        // log.info(LogConstant.SPRING_LOG, "控制层日志切面 afterReturning");
    }

    /** 方法抛出异常退出时执行的通知 */
    @AfterThrowing("pointcut()")
    public void afterThrowing() {
        // log.info(LogConstant.SPRING_LOG, "控制层日志切面 AfterThrowing");
    }

}